from helpers.mengy_bytes_helper import str2Bytes
import functools

INITIAL_MODBUS = 0xFFFF
INITIAL_DF1 = 0x0000


class CRC_PACK(object):
    """docstring for CRC_PACK"""

    def __init__(self,):
        self.table = CRC_PACK.init_table()

    @classmethod
    def init_table(cls):
        # Initialize the CRC-16 table,
        #   build a 256-entry list, then convert to read-only tuple
        lst = []
        for i in range(256):
            data = i << 1
            crc = 0
            for j in range(8, 0, -1):
                data >>= 1
                if (data ^ crc) & 0x0001:
                    crc = (crc >> 1) ^ 0xA001
                else:
                    crc >>= 1
            lst.append(crc)
        table = tuple(lst)
        return table

    def calc_b_Str(self, b_st, crc=INITIAL_MODBUS):
        """Given a bunary string and starting CRC, Calc a final CRC-16 """
        for ch in b_st:
            crc = (crc >> 8) ^ self.table[(crc ^ ch) & 0xFF]
        return crc

    def crc_chreck(self, st):
        return 0 == self.calc_b_Str(st)

    @functools.lru_cache(maxsize=1024)
    def gen_st_crc(self, a):
        b = str2Bytes(a)
        c = self.calc_b_Str(b)
        d = bytes([c % 256, c // 256])
        return b + d

    def check_crc_bytes(self, b: bytes):
        reult = self.calc_b_Str(b)
        return reult == 0

    def check_crc_str(self, a: str):
        b = str2Bytes(a)
        return self.check_crc_bytes(b)


# cp = CRC_PACK()
# cp.gen_st_crc("0123456")
# cp.check_crc_bytes(b'\x01\x23\x45\x06\x42\x80')
# cp.check_crc_str("01 23 45 06 42 80")
